package com.beaven.imserver.net.factory;

import com.beaven.imserver.net.bean.db.Category;
import com.beaven.imserver.net.bean.db.User;
import com.beaven.imserver.net.bean.db.UserFollow;
import com.beaven.imserver.net.utils.HibUtil;
import com.beaven.imserver.net.utils.TextUtil;
import com.google.common.base.Strings;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * author: Beaven
 * time: 2017/5/17 17:39
 */
public class UserFactory {

  public static final String CATEGORY_DEFAULT = "我的好友";

  public static String account = "http://oj03vlyk7.bkt.clouddn.com/image/im/%d.png";

  // 帐号登陆
  public static User login(String account, String password) {
    return HibUtil.query(session -> (User) session.createQuery(
        "from User where phone=:phone and password=:password")
        .setParameter("phone", account.trim())
        .setParameter("password", password)
        .uniqueResult());
  }

  public static User login(User user) {
    String token = UUID.randomUUID().toString();
    token = TextUtil.encodeBase64(token);
    user.setToken(token);
    return updateUser(user);
  }

  // 帐号注册
  public static User register(String account, String password, String name) {
    account = account.trim();
    return createUser(account, password, name);
  }

  private static User createUser(String account, String password, String name) {
    User user = new User();
    user.setName(name);
    user.setPhone(account);
    user.setPassword(password);
    user.setAccount(String.format(UserFactory.account, TextUtil.getRandomNumber(1, 9)));
    user.setChatColor(TextUtil.getRandomNumber(0, 3));
    User user1 = HibUtil.query(session -> {
      session.save(user);
      return user;
    });
    CategoryFactory.create(CATEGORY_DEFAULT, user1);
    return user1;
  }

  // 根据Token查询个人信息
  public static User findByToken(String token) {
    return HibUtil.query(session -> (User) session.createQuery("from User where token=:token")
        .setParameter("token", token)
        .uniqueResult());
  }

  // 通过姓名查找
  public static User findByName(String name) {
    return HibUtil.query(session -> (User) session.createQuery("from User where name=:name")
        .setParameter("name", name).uniqueResult());
  }

  // 帐号查找，手机号
  public static User findByAccount(String phone) {
    return HibUtil.query(session -> (User) session.createQuery("from  User where phone=:phone")
        .setParameter("phone", phone)
        .uniqueResult());
  }

  // Id查询
  public static User findById(String id) {
    return HibUtil.query(session -> session.get(User.class, id));
  }

  // 更新用户信息
  public static User updateUser(User user) {
    return HibUtil.query(session -> {
      session.saveOrUpdate(user);
      return user;
    });
  }

  // 用户绑定pushId
  public static User bindPushId(User user, String pushId) {
    if (Strings.isNullOrEmpty(pushId)) {
      return null;
    }

    // 解除原有pushId绑定
    HibUtil.queryOnly(session -> {
      @SuppressWarnings("unchecked")
      List<User> userList = (List<User>) session
          .createQuery("from User where lower(pushId)=:pushId and id!=:userId")
          .setParameter("pushId", pushId.toLowerCase())
          .setParameter("userId", user.getId())
          .list();

      for (User user1 : userList) {
        user1.setPushId(null);
        session.saveOrUpdate(user1);
      }
    });

    if (pushId.equals(user.getPushId())) {
      return user;
    } else {
      if (!Strings.isNullOrEmpty(user.getPushId())) {
        PushFactory.pushLogout(user);
      }
      // 重新绑定
      user.setPushId(pushId);
      return updateUser(user);
    }
  }

  // 获取我的好友列表
  public static List<User> contacts(User self) {
    return HibUtil.query(session -> {
      session.load(self, self.getId());
      return self.getFollowing().stream().map(UserFollow::getTarget).collect(Collectors.toList());
    });
  }

  // 添加联系人
  public static User follow(User origin, User target, Category category, String alias) {
    UserFollow userFollow = getUserFollow(origin, target);
    if (userFollow != null) {
      return userFollow.getTarget();
    }

    return HibUtil.query(session -> {
      session.load(origin, origin.getId());
      session.load(target, target.getId());

      UserFollow originFollow = new UserFollow();
      originFollow.setOrigin(origin);
      originFollow.setTarget(target);
      originFollow.setCategory(category);
      originFollow.setAlias(alias);

      UserFollow targetFollow = new UserFollow();
      Category category1 = CategoryFactory.queryByName(target, CATEGORY_DEFAULT);
      targetFollow.setOrigin(target);
      targetFollow.setTarget(origin);
      targetFollow.setCategory(category1);

      session.save(originFollow);
      session.save(targetFollow);
      return target;
    });
  }

  // 删除联系人
  public static void delete(User origin, User target) {
    UserFollow originUserFollow = getUserFollow(origin, target);
    UserFollow targetUserFollow = getUserFollow(target, origin);
    if (originUserFollow == null || targetUserFollow == null) {
      return;
    }
    HibUtil.queryOnly(session -> {
      session.load(origin, origin.getId());
      session.load(target, target.getId());

      session.delete(originUserFollow);
      session.delete(targetUserFollow);
    });
  }

  // 查找用户间的关系
  public static UserFollow getUserFollow(User origin, User target) {
    return HibUtil.query(session -> (UserFollow) session.createQuery(
        "from UserFollow where originId=:originId and targetId=:targetId")
        .setParameter("originId", origin.getId())
        .setParameter("targetId", target.getId())
        .setMaxResults(1)
        .uniqueResult());
  }

  // 搜索用户,匹配名称和帐号
  @SuppressWarnings("unchecked")
  public static List<User> searchUser(String name) {
    if (Strings.isNullOrEmpty(name)) {
      name = "";
    }
    // 模糊匹配
    String searchName = "%" + name + "%";

    return HibUtil.query(session -> (List<User>) session.createQuery(
        "from User where lower(name) like :name or phone like :name")
        .setParameter("name", searchName)
        .setMaxResults(20) // 至多20条
        .list());
  }
}
